//////////////////////////////////////////////////////////////////////////////
//
//  Created by Philip Mulcahy on 09/02/2012.
//  Copyright (c) 2012 Philip Mulcahy. All rights reserved.
//
//  This file is part of the note-recog library.
//
//  note-recog is free software: you can redistribute it and/or modify
//  it under the terms of version 3 of the GNU Lesser General Public License 
//  as published by the Free Software Foundation.
//
//  note-recog is distributed is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with note-recog.  If not, see <http://www.gnu.org/licenses/>.
//
//////////////////////////////////////////////////////////////////////////////

#ifndef note_recog_Log_h
#define note_recog_Log_h

#include <iostream>
#import <QuartzCore/CABase.h>

class Logger
{
private:    
    template< typename T >
    friend std::ostream& operator<<( Logger& log, T& rhs );    
    
    const static double s_startTime; 
    const char * const _name;
    Logger( const Logger& ); // not implemented
    Logger(); // not implemented
    
    static float getTime();
    
public:
    Logger( const char* name ) :
      _name(name)
    {}
    
    const char* name() const { return _name; }
};

template< typename T >
std::ostream& operator<<( Logger& log, T& rhs )
{
    std::cout << Logger::getTime() << " " << log.name() << " " << rhs;
    return std::cout;
}

#define LOG_DECLARE static Logger s_logger
#define LOG_DEFINE( name ) Logger name::s_logger( #name )

#define LOG( level, message ) ( s_logger << level << " " << message << std::endl )

#ifdef LOG_LEVEL_TRACE
# define LOG_TRACE( message ) LOG( "TRACE", message )
# define LOG_LEVEL_DEBUG 
#else
# define LOG_TRACE( message )
#endif

#ifdef LOG_LEVEL_DEBUG
# define LOG_DEBUG( message ) LOG( "DEBUG", message )
# define LOG_LEVEL_INFO 
#else
# define LOG_DEBUG( message )
#endif

#ifdef LOG_LEVEL_INFO
# define LOG_INFO( message ) LOG( "INFO", message )
#else
# define LOG_INFO( message )
#endif

#define LOG_WARN(  message ) LOG( "WARN",  message )
#define LOG_ERROR( message ) LOG( "ERROR", message )
#define LOG_FATAL( message ) LOG( "FATAL", message )

#define LOG_THROW( exception ) { LOG( "THROW", exception.what() ); throw exception; }


#endif
